home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16.lha / Python-1.6 / Lib / Python1.6 / distutils / spawn.py < prev    next >
Encoding:
Python Source  |  2000-08-02  |  5.6 KB  |  167 lines

  1. """distutils.spawn
  2.  
  3. Provides the 'spawn()' function, a front-end to various platform-
  4. specific functions for launching another program in a sub-process.
  5. Also provides the 'find_executable()' to search the path for a given
  6. executable name. """
  7.  
  8. # created 1999/07/24, Greg Ward
  9.  
  10. __revision__ = "$Id: spawn.py,v 1.9 2000/08/02 01:08:02 gward Exp $"
  11.  
  12. import sys, os, string
  13. from distutils.errors import *
  14.  
  15.  
  16. def spawn (cmd,
  17.            search_path=1,
  18.            verbose=0,
  19.            dry_run=0):
  20.  
  21.     """Run another program, specified as a command list 'cmd', in a new
  22.        process.  'cmd' is just the argument list for the new process, ie.
  23.        cmd[0] is the program to run and cmd[1:] are the rest of its
  24.        arguments.  There is no way to run a program with a name different
  25.        from that of its executable.
  26.  
  27.        If 'search_path' is true (the default), the system's executable
  28.        search path will be used to find the program; otherwise, cmd[0] must
  29.        be the exact path to the executable.  If 'verbose' is true, a
  30.        one-line summary of the command will be printed before it is run.
  31.        If 'dry_run' is true, the command will not actually be run.
  32.  
  33.        Raise DistutilsExecError if running the program fails in any way;
  34.        just return on success."""
  35.  
  36.     if os.name == 'posix':
  37.         _spawn_posix (cmd, search_path, verbose, dry_run)
  38.     elif os.name == 'nt':
  39.         _spawn_nt (cmd, search_path, verbose, dry_run)
  40.     else:
  41.         raise DistutilsPlatformError, \
  42.               "don't know how to spawn programs on platform '%s'" % os.name
  43.  
  44. # spawn ()
  45.  
  46.  
  47. def _nt_quote_args (args):
  48.     """Obscure quoting command line arguments on NT.
  49.        Simply quote every argument which contains blanks."""
  50.  
  51.     # XXX this doesn't seem very robust to me -- but if the Windows guys
  52.     # say it'll work, I guess I'll have to accept it.  (What if an arg
  53.     # contains quotes?  What other magic characters, other than spaces,
  54.     # have to be escaped?  Is there an escaping mechanism other than
  55.     # quoting?)
  56.  
  57.     for i in range (len (args)):
  58.         if string.find (args[i], ' ') != -1:
  59.             args[i] = '"%s"' % args[i]
  60.     return args
  61.  
  62. def _spawn_nt (cmd,
  63.                search_path=1,
  64.                verbose=0,
  65.                dry_run=0):
  66.  
  67.     executable = cmd[0]
  68.     cmd = _nt_quote_args (cmd)
  69.     if search_path:
  70.         # either we find one or it stays the same
  71.         executable = find_executable(executable) or executable 
  72.     if verbose:
  73.         print string.join ([executable] + cmd[1:], ' ')
  74.     if not dry_run:
  75.         # spawn for NT requires a full path to the .exe
  76.         try:
  77.             rc = os.spawnv (os.P_WAIT, executable, cmd)
  78.         except OSError, exc:
  79.             # this seems to happen when the command isn't found
  80.             raise DistutilsExecError, \
  81.                   "command '%s' failed: %s" % (cmd[0], exc[-1])
  82.         if rc != 0:
  83.             # and this reflects the command running but failing
  84.             raise DistutilsExecError, \
  85.                   "command '%s' failed with exit status %d" % (cmd[0], rc)
  86.  
  87.                 
  88. def _spawn_posix (cmd,
  89.                   search_path=1,
  90.                   verbose=0,
  91.                   dry_run=0):
  92.  
  93.     if verbose:
  94.         print string.join (cmd, ' ')
  95.     if dry_run:
  96.         return
  97.     exec_fn = search_path and os.execvp or os.execv
  98.  
  99.     pid = os.fork ()
  100.  
  101.     if pid == 0:                        # in the child
  102.         try:
  103.             #print "cmd[0] =", cmd[0]
  104.             #print "cmd =", cmd
  105.             exec_fn (cmd[0], cmd)
  106.         except OSError, e:
  107.             sys.stderr.write ("unable to execute %s: %s\n" %
  108.                               (cmd[0], e.strerror))
  109.             os._exit (1)
  110.             
  111.         sys.stderr.write ("unable to execute %s for unknown reasons" % cmd[0])
  112.         os._exit (1)
  113.  
  114.     
  115.     else:                               # in the parent
  116.         # Loop until the child either exits or is terminated by a signal
  117.         # (ie. keep waiting if it's merely stopped)
  118.         while 1:
  119.             (pid, status) = os.waitpid (pid, 0)
  120.             if os.WIFSIGNALED (status):
  121.                 raise DistutilsExecError, \
  122.                       "command '%s' terminated by signal %d" % \
  123.                       (cmd[0], os.WTERMSIG (status))
  124.  
  125.             elif os.WIFEXITED (status):
  126.                 exit_status = os.WEXITSTATUS (status)
  127.                 if exit_status == 0:
  128.                     return              # hey, it succeeded!
  129.                 else:
  130.                     raise DistutilsExecError, \
  131.                           "command '%s' failed with exit status %d" % \
  132.                           (cmd[0], exit_status)
  133.         
  134.             elif os.WIFSTOPPED (status):
  135.                 continue
  136.  
  137.             else:
  138.                 raise DistutilsExecError, \
  139.                       "unknown error executing '%s': termination status %d" % \
  140.                       (cmd[0], status)
  141. # _spawn_posix ()
  142.  
  143.  
  144. def find_executable(executable, path=None):
  145.     """Try to find 'executable' in the directories listed in 'path' (a
  146.     string listing directories separated by 'os.pathsep'; defaults to
  147.     os.environ['PATH']).  Returns the complete filename or None if not
  148.     found.
  149.     """
  150.     if path is None:
  151.         path = os.environ['PATH']
  152.     paths = string.split(path, os.pathsep)
  153.     (base, ext) = os.path.splitext(executable)
  154.     if (sys.platform == 'win32') and (ext != '.exe'):
  155.         executable = executable + '.exe'
  156.     if not os.path.isfile(executable):
  157.         for p in paths:
  158.             f = os.path.join(p, executable)
  159.             if os.path.isfile(f):
  160.                 # the file exists, we have a shot at spawn working
  161.                 return f
  162.         return None
  163.     else:
  164.         return executable
  165.  
  166. # find_executable()    
  167.